---用户系统api
--@function
local _usr = class("UserCenter", require("framework.cls.basehandler"))
--======================================
--default params
local d = Ding
local Logger = d.Logger

local ngx = ngx
local n_req = ngx.req
local n_thread_wait = ngx.thread.wait
local n_thread_spwan = ngx.thread.spawn
local resty_md5 = require("resty.md5")
local resty_string = require("resty.string")
--======================================
-- 枚举 登录错误
local ENUM_LOGIN_ERROR = {
    ["USER_NOT_EXISTS"] = 101,
    ["ERROR_PWD"] = 102,
    ["CACHE_CERTIFICATION_FAILED"] = 103,
    ["REFRESH_TOKEN_FAILED"] = 104,
    ["USERNAME_ALREADY_EXIST"] = 105,
    ["REGISTER_NEWUSER_FAILED"] = 106
}

local ENUM_ERROR_TIPS = {
    [101] = "user not exists!",
    [102] = "error password",
    [103] = "usr cachetoken failed",
    [104]  = "refresh token failed!",
    [105] = "username already exist!",
    [106] = "register new user failed!"
}

local ENUM_SCOPE_LIST = {
    USER_INFO = "user_info"       --用户信息
}


--- 密码比较
-- MD5 UPPER直接比较
-- @tparam  string pwd 用户输入的密码
-- @tparam  string tarstr 存储的md5值
-- @treturn boolean 是否匹配.
local function chk_md5_pwd(pwd, tarstr)
    local md5 = resty_md5.new()
    md5:update(pwd)
    local digest = md5:final()
    Logger:debug("PWD %s comp %s", tarstr, resty_string.to_hex(digest))
    return string.upper(tarstr) == string.upper(resty_string.to_hex(digest))
end


function _usr:ctor(svr, orm_usr, orm_actusr)
    _usr.super.ctor(self, "user", svr)
    d.bind(self, "base_decorator")
    d.bind(self, "auth_decorator")

    self._orm_usr = orm_usr
    self._orm_actusr = orm_actusr
end

--[[--
管理员登录
]]
function _usr:get_adminlogin()
    local reqdata = ngx.req.get_uri_args() or {}
    Logger:dump(reqdata, "--->>reqdata")
    --statu 0
    local rep = {
        status = 0
    }
    local unionid = reqdata["unionid"]
    local ischktoken = reqdata["accesstoken"] and reqdata["refreshtoken"]
    if ischktoken then 
        --todo 
    else  
        
    end 
    self:doret(rep)
end

--- 手机登录
-- 使用手机号及验证码登录 TODO 暂时是手机号加密码
-- @tparam  table self self
function _usr:post_phonelogin()
    local ok, reqdata = self:body_jsonparams_nec_({
        "mphone",
        "password"
    })
    if not ok then return end 
    local o_usr = self._orm_usr:find({mphone=reqdata["mphone"]})
    local retcode = 0
    if not o_usr then 
        retcode = ENUM_LOGIN_ERROR["USER_NOT_EXISTS"]
    else 
        if (not chk_md5_pwd(reqdata["password"], o_usr["password"])) then 
            retcode = ENUM_LOGIN_ERROR["ERROR_PWD"]
        else 
            if not (self:_cache_certificate(o_usr["gid"], o_usr["scope"])) then 
                retcode = ENUM_LOGIN_ERROR["CACHE_CERTIFICATION_FAILED"]
            end
        end
    end
    
    if retcode ~= 0 then 
        self:doerror(retcode, ENUM_ERROR_TIPS[retcode])
    else 
        local ret = {}
        table.merge(ret, self:_get_certificate())
        self:_chk_login_scope(ret, reqdata["scope"], o_usr)
        self:doret(ret)  
    end
end

--- 用户名密码登录
-- 直接使用用户名密码登录
-- @tparam  table self 
function _usr:post_userpwdlogin()
    local ok, reqdata = self:body_jsonparams_nec_({
        "username",
        "password"
    })
    if not ok then return end 
    local o_usr = self._orm_usr:find({username=reqdata["username"]})
    local retcode = 0
    if not o_usr then 
        retcode = ENUM_LOGIN_ERROR["USER_NOT_EXISTS"]
    else 
        if (not chk_md5_pwd(tostring(reqdata["password"]), tostring(o_usr["password"]))) then 
            retcode = ENUM_LOGIN_ERROR["ERROR_PWD"]
        else 
            if not (self:_cache_certificate(o_usr["gid"], o_usr["scope"])) then 
                retcode = ENUM_LOGIN_ERROR["CACHE_CERTIFICATION_FAILED"]
            end
        end
    end
    
    if retcode ~= 0 then 
        self:doerror(retcode, ENUM_ERROR_TIPS[retcode])
    else 
        local ret = {}
        table.merge(ret, self:_get_certificate())
        self:_chk_login_scope(ret, reqdata["scope"], o_usr)
        self:doret(ret)  
    end
end

--- 添加用户
-- 添加使用用户名密码的用户（开通非注册方式）
-- @tparam  table self 
function _usr:post_add_pwdusr()
    local ok, reqdata = self:body_jsonparams_nec_({
        "username",
        "password",
        "nickname",
        "roletype"
    })
    if not ok then return end 
    local retcode = 0
    local o_usr = self._orm_usr:find({username=reqdata["username"]})
    if o_usr then 
        retcode = ENUM_LOGIN_ERROR["USERNAME_ALREADY_EXIST"]
    else 
        local ok = self._orm_usr:new_insert(reqdata["username"], reqdata["password"], reqdata["nickname"], reqdata["roletype"])
        if not ok then 
            retcode = ENUM_LOGIN_ERROR["REGISTER_NEWUSER_FAILED"]
        end
    end
    if retcode == 0 then 
        self:doret()
    else 
        self:doerror(retcode, ENUM_ERROR_TIPS[retcode])
    end
end 

function _usr:get_refreshtoken()
    local ok, reqdata = self:url_jsonparams_nec_({
        "gid",
        "refresh_token"
    })
    if not ok then return end  
    local retcode = 0
    local issuc, reftoken, expire_in = self._orm_actusr:refresh_token(reqdata["gid"], reqdata["refresh_token"])
    if not issuc then 
        retcode = ENUM_LOGIN_ERROR["REFRESH_TOKEN_FAILED"]
    end
    if retcode ~= 0 then 
        self:doerror(retcode, ENUM_ERROR_TIPS[retcode])
    else 
        local ret = {
            token = reftoken, 
            expire_in = expire_in
        }
        self:doret(ret)  
    end
end

function _usr:get_userinfo()
    local ok, reqdata = self:url_jsonparams_nec_()
    if not ok then return end 

    ok = self:base_auth_(ngx.req)
    if not ok then return end 
    local gid = ngx.req.get_headers()['X-D-GID']
    local o_usr = self._orm_usr:find({gid=gid})
    local retcode = 0
    if not o_usr then 
        retcode = ENUM_LOGIN_ERROR["USER_NOT_EXISTS"]
    end
    
    if retcode ~= 0 then 
        self:doerror(retcode, ENUM_ERROR_TIPS[retcode])
    else 
        local ret = {}
        self:doret(o_usr)  
    end
end

--[[ 内部接口 ]]
function _usr:get_islogin()
    local ok, reqdata = self:url_jsonparams_nec_({
        "gid"
    })
    Logger:info("--->>>islogin %s", tostring(ok))
    if not ok then return end
    local retcode = 0
    local gid = reqdata["gid"]
    local o_usr
    local is_token = self._orm_actusr:find({gid = gid})
    Logger:info("--->>>istoken %s", tostring(is_token))
    if is_token then 
        o_usr = self._orm_usr:find({gid = gid})
        if not o_usr then 
            retcode = ENUM_LOGIN_ERROR["USER_NOT_EXISTS"]
        end
    else 
        retcode = ENUM_LOGIN_ERROR["USER_NOT_EXISTS"]
    end
    Logger:info("--->>>not retcode =  %s", tostring(retcode))
    if retcode == 0 then 
        self:doret(o_usr)
    else 
        self:doerror(retcode, ENUM_ERROR_TIPS[retcode]) 
    end
end
--======================================================================
--一下是实现所需私有方法
--======================================================================

--用户登录信息范围
function _usr:_chk_login_scope(retdic, scope, usrinfo)
    scope = scope or ENUM_SCOPE_LIST["USER_INFO"]
    if scope == ENUM_SCOPE_LIST["USER_INFO"] then 
        retdic[scope] = usrinfo
    end
end  

-- token 处理
function _usr:_cache_certificate(...)   --gid, scope
    return self._orm_actusr:cache_tokens(...)
end

-- 获取刚存的 token 
function _usr:_get_certificate()
    return self._orm_actusr:get_model()    
end

return _usr
